package com.netty.clientserver.strategy.impl;

import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.netty.clientserver.command.Command;
import com.netty.clientserver.packet.SingleMessage;
import com.netty.clientserver.packet.base.Packet;
import com.netty.clientserver.packet.response.ResponseVo;
import com.netty.clientserver.strategy.TypeStrategy;
import com.netty.clientserver.util.ConnectUtils;
import com.netty.common.constant.MqConstants;
import com.netty.common.entity.mq.MqMessage;
import com.netty.common.util.RedisUtil;
import com.netty.common.util.UUID;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ConnectTimeoutException;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/** 私聊
 * @author LiuXiaoYu
 * @date 2022/2/3- 14:24
 */
@Component("1")
@DependsOn("mqConfig")
@Slf4j
public class SingleTypeStrategyImpl implements TypeStrategy {
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Override
    public Packet execute(Channel channel,String type, String content) {
        System.out.println("私聊开始");
        //转换为指定私聊类型
        SingleMessage singleMessage = JSONObject.parseObject(content, new TypeReference<SingleMessage>() {});
        String uuid=UUID.getUUID();
        if (singleMessage.getUuid()==null||"".equals(singleMessage.getUuid())){
            singleMessage.setUuid(uuid);
        }
        String userId = ConnectUtils.getUserId(channel);
        //判断收到消息的人是否绑定了channel 这个只是绑定userId和channel 没确定点对点私聊
        boolean bindChannel = ConnectUtils.isBindChannel(String.valueOf(singleMessage.getToId()));
        //如果对方绑定了channel
        if (bindChannel){
            //拿到对方的channel 可能对方绑定了channel但是私聊的对象不是你
            Channel toUserChannel = ConnectUtils.isBind(String.valueOf(singleMessage.getToId()));
            /*这里得判断不是群聊channel并且还是你指定要私聊的人才行
            1对2进行私聊 他们俩都绑定了  3对1私聊时应该让1收不到消息 并判定1离线
            感觉还需要一个东西来存储 或者说绑定时的设计就是有问题的
            解决新增一个map*/
            if (toUserChannel!=null&&ConnectUtils.whetherGroupChannel(toUserChannel)&&ConnectUtils.peerToPeerPrivateChat(channel)){
                //组成完整的数据格式
                ByteBuf byteBuf = getByteBuf(channel,singleMessage.getOwner(),singleMessage.getOwnerImage(),singleMessage.getFileType(),singleMessage.getMessage());
                //写出消息
                toUserChannel.writeAndFlush(new TextWebSocketFrame(byteBuf));
            }
        }
        //这是真正的入库消息
        com.netty.common.entity.Message msg=new com.netty.common.entity.Message()
                .setInfoContent(singleMessage.getMessage())
                .setToId(singleMessage.getToId())
                .setOnline(bindChannel&&ConnectUtils.whetherGroupChannel(ConnectUtils.isBind(String.valueOf(singleMessage.getToId())))&&ConnectUtils.peerToPeerPrivateChat(channel))
                .setFromId(Integer.parseInt(userId))
                .setSingleMessage(Integer.parseInt(type)==1)
                .setSendTime(new Date());

        String messageToDataBase=JSON.toJSONString(msg);
       //生成mq消息日志log 即MqMessage 这是存储在mq的消息日志
        MqMessage messageLog = new MqMessage()
                .setMessage(messageToDataBase)
                .setMessageId(uuid)
                .setExchange(MqConstants.NETTY_MESSAGE_EXCHANGE)
                .setRoutingKey(MqConstants.NETTY_MESSAGE_ROUTING_KEY)
                //设置状态0：投递中
                .setStatus(MqConstants.MESSAGE_DELIVERED)
                //设置重试次数为0
                .setRetryCount(MqConstants.MESSAGE_RETRY_COUNT);
        //存放到redis里面 可能会出现网络故障 没有存储进去
        redisUtil.set(MqConstants.NETTY_MESSAGE_LOG_KEY+uuid,messageLog);
        //不论对方是否在线都要mq发消息入库(clientserver)
        Message message = MessageBuilder.withBody(messageToDataBase.getBytes()).setMessageId(uuid).build();
        rabbitTemplate.convertAndSend(messageLog.getExchange(),messageLog.getRoutingKey(),message,new CorrelationData(uuid));


        System.out.println(bindChannel&&ConnectUtils.whetherGroupChannel(ConnectUtils.isBind(String.valueOf(singleMessage.getToId())))&&ConnectUtils.peerToPeerPrivateChat(channel)?singleMessage.getToId()+"号用户在线":singleMessage.getToId()+"号用户不在线"+","+userId + "号用户给" + singleMessage.getToId() + "号用户发送了消息:" + singleMessage.getMessage());
        return singleMessage;
    }

    /**
     * 将自己的私聊信息转发给对方显示
     * @param channel
     * @param fileType
     * @param message
     * @return
     */
    public static ByteBuf getByteBuf(Channel channel,String owner,String ownerImage,String fileType,String message) {
        ByteBuf byteBuf = channel.alloc().buffer();
        ResponseVo responseVo = new ResponseVo()
                .setType(Command.MESSAGE_RESPONSE)
                .setFileType(fileType)
                .setOwner(owner)
                .setOwnerImage(ownerImage)
                .setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .setMessage(message).setStatus(HttpStatus.HTTP_OK);
        byte []bytes =  JSONObject.toJSONString(responseVo).getBytes(StandardCharsets.UTF_8);
        byteBuf.writeBytes(bytes);
        return byteBuf;
    }
}
